﻿#ifndef _SERIAL_FILE_BASE_H_
#define _SERIAL_FILE_BASE_H_

#include "crossplat_def.h"

class CSerialFileBase
{
public:
	CSerialFileBase();
	~CSerialFileBase();
public:
	//实现类似文件操作最基本的5个API fopen, fclose,fwrite,fread,fseek.
	virtual int Open(void * file,uint64_t fileLBA, uint32_t fileSpace, int acess_mod) = 0;

	virtual int Close() = 0;
	virtual int ReOpen() = 0; //重新再打开同样一个文件
	virtual int Seek(int32_t offset,int whence)=0;

	virtual int Read (uchar_t * pBuf, uint32_t dataSize, bool bLock = true) = 0;

	virtual int Write(uchar_t * pBuf, uint32_t dataSize, bool bLock = true)= 0;

	virtual int ReadPos(uint32_t offset, uchar_t * pBuf, uint32_t dataSize, bool bLock = true) = 0;

	virtual int WritePos(uint32_t offset, uchar_t * pBuf, uint32_t dataSize, bool bLock = true) = 0;

	virtual void Flush()=0;
	//主要是录像专用的接口
	virtual int WriteCachePos(uint32_t offset, uchar_t * pBuf, uint32_t dataSize, bool bLock = true) = 0;
	
	virtual uint32_t get_cur_offset(bool bReal = false) = 0;

	virtual int FillTotalSpace() = 0;
	static int CopyFile(CSerialFileBase * src, CSerialFileBase * dest,uint32_t appoint_bufsz);
	//复制文件中指定大小的数据到新文件
	static int CopyFileBySize(CSerialFileBase * src, CSerialFileBase * dest,uint32_t appoint_bufsz,uint32_t appoint_sz);
	//分配磁盘空间，只支持通用文件系统的预分配
	static int  AllocSpace(const char * filePath,uint32_t fileSpace);
	static bool IsRawDevice(const char * diskPath);
public://内联函数
	//是否打开记录时间功能***************************************
	void SwitchRecordTime(bool bRecord)
	{
		m_bRecordWtTime = bRecord;
	}

	bool IsOpened()
	{
		if(m_access_mod != SCSI_CLOSED)
			return true;
		else
			return false;
	}

	uint64_t get_lba_start()
	{
		return m_baseLBA;
	}

	uint64_t get_lba_end()
	{
		return m_baseLBA + m_fileSize/m_sec_size;
	}

	uint32_t get_data_size()
	{
		return m_fileSize;
	}

	uint32_t get_sec_size()
	{
		return m_sec_size;
	}

	void Lock()
	{
		if(NULL != m_pLock)
			CROSS_LOCK(m_pLock);
	}

	void Unlock()
	{
		if(NULL != m_pLock)
			CROSS_UNLOCK(m_pLock);
	}

	bool is_closed()
	{
		if(m_access_mod == -1)
		{
			return true;
		}
		return false;
	}
	bool IsOverFileArea(int addSize)
	{
		return ((m_cur_offset + addSize) > m_fileSize) ? true :false;
	}
	bool IsOverFileArea(int addSize,uint32_t offset)
	{
		return ((offset + addSize) > m_fileSize) ? true :false;
	}
	int GetLastErr()
	{
		return m_lastRet;
	}
	int GetStatus()
	{
		return m_status;
	}
	void set_resualt(int ret)
	{
		m_status = ret;
	}
	int64_t  GetLastWtTime()
	{
		return m_lastWtTime;
	}
	void set_file_area(uint32_t endOffset)
	{
		m_fileSize = endOffset;
	}
	uint32_t getLeafSize(uint32_t curPos)
	{
		if(curPos > m_fileSize)
		{
			return 0;
		}
		else
		{
			return m_fileSize - curPos;
		}
	}
	char * get_device_name()
	{
		return m_storage_file;
	}
	void SetLastWriteTm()
	{
		time_t curTm;
		time(&curTm);
		m_lastWtTime = (int64_t)curTm*1000;
	}
protected:
	char        m_storage_file[250];     //存储文件，裸磁盘/dev/sd  或者 正常文件 ,或者是sd卡 /dev/
	uint32_t    m_sec_size;				//硬盘扇区的大小
	uint64_t    m_baseLBA;				//文件所在扇区首地址
	uint32_t    m_fileSize;				//文件大小
	int         m_access_mod;			//读写控制
	bool		m_bRecordWtTime;		//是否记录最后写入时间
	int			m_status;				//0:表示正常 1：表示正在写入， 2：正在读取 小于0为错误码
	int			m_lastRet;	            //最后的错误码
	uint32_t    m_cur_offset;			//当前的位置，字节数

	//数据对齐缓冲，
	uchar_t*	m_align_buf;			//对齐BUF，标准配备,分区当前硬盘扇区的大小

	//缓冲功能缓冲，主要针对于写入，由于数据大小是对齐到512字节的，但是写入又是连续的。
	//可以将数据缓冲一部分，减少不必要的磁盘IO操作，主要针对于写入数据
	uchar_t*    m_cache_buf;
	uint32_t    m_cache_pos;

	int64_t     m_lastWtTime;			//最后写入数据的时间
	cross_lock_t *  m_pLock;			//磁盘互斥锁
};


#endif //_SERIAL_FILE_H_
